/*
 * Reaction.h
 *
 *  Created on: 23 May 2011
 *      Author: allan
 */

#ifndef REACTION_H_
#define REACTION_H_

// C++ includes
#include <iostream>
#include <functional>
#include <memory>
#include <tuple>
using namespace std;

// Eigen includes
#include <Eigen/Core>
using namespace Eigen;

// GeoReact includes
#include "EquilibriumConstantData.h"
#include "ReactionKinetics.h"
#include "Utils.h"
#include "Reaction.h"

class Reaction
{
public:
	/// --- Type definitions --- ///
	typedef std::shared_ptr<ReactionKinetics> ReactionKineticsPtr;
	
public:
	/// --- Auxiliary structures --- ///
	struct Species
	{ string name; Index index; double stoichiometry; };
	
public:
	/// --- Constructor and destructor methods --- ///
	Reaction();
	
	/// --- Mutator methods --- ///
	void
	SetEquation(const string& reactant, const vector<string>& products, const vector<double>& stoichiometries); 
	
	void
	SetEquilibriumConstantData(const EquilibriumConstantData& eqConstant);
	
	void
	SetReactionKinetics(const ReactionKineticsPtr& kinetics);
	
	void
	SetIndexes(const SpeciesMap& speciesMap);
	
	/// --- Accessor methods --- ///
	const Species&
	GetReactant() const;
	
	const vector<Species>&
	GetProducts() const;
	
	const EquilibriumConstantData&
	GetEquilibriumConstantData() const;
	
	/// --- General reaction related methods --- ///
	const double
	EquilibriumConstant(double T, double P) const;
	
	const double
	ReactionQuotient(const VectorXd& a) const;
	
	/// --- Kinetic rate methods --- ///
	const double
	MassRate(double T, double P, const VectorXd& n, const VectorXd& a) const;
	
	friend ostream& 
	operator<<(ostream& out, const Reaction& reaction);
	
private:
	/// The reactant of the reaction
	Species reactant;
	
	/// The products of the reaction
	vector<Species> products;
	
	/// The equilibrium constants of the reaction over a set of temperature points
	EquilibriumConstantData eqConstant;
	
	/// The pointer to the kinetics object that is responsible to handle the kinetic rate laws of this reaction 
	ReactionKineticsPtr kinetics;
};

/// --- Utilities methods --- ////
ostream& operator<<(ostream& out, const Reaction& reaction);

#endif /* REACTION_H_ */
